module AlohaP{
		
	//Radio
	provides interface AlohaSend;
	provides interface AlohaReceive;
	provides interface AlohaState;

	//Low Level radio
	uses interface RadioSend as MulleSend;
	uses interface RadioReceive as MulleReceive;
	uses interface RadioState as MulleState;
	uses interface Packet;
	uses interface AMPacket;

	//Timers
	uses interface Timer<TMilli> as Timer0;

	//Other
	uses interface Leds;
	
}
implementation{
	
	//Globals
	norace uint8_t g_state = STATE_OFF;
	norace uint8_t g_sendState = SENDER_NOT_RTX;
	//norace uint8_t g_rcvState = 
	norace uint8_t g_channel = 0;
	
	myData_t g_myData;
	myData_t g_myData_rcv;
	message_t pkt_snd, pkt_rcv;
	

	/*******************************************************************************************************************
	 * 
	 *   Interface AlohaSend
	 * 
	 ******************************************************************************************************************/
	
	command error_t AlohaSend.send(myData_t* msg){
		
		uint8_t oldState;
		error_t myError;
		myData_t * testMsg = NULL;
		
		//call Leds.led0Toggle();
		
		if(g_state != STATE_ON)
			return EBUSY;
		
		atomic oldState= g_state;
		atomic g_state = STATE_SND;
		
		testMsg = (myData_t *)(call Packet.getPayload(&pkt_snd,sizeof(myData_t)));
		testMsg->uid = 111;
		testMsg->counter = 111;
		testMsg->data = 111;
		
		call AMPacket.setSource(&pkt_snd, call AMPacket.address());
		call AMPacket.setDestination(&pkt_snd, 1);
	
		call AMPacket.setGroup(&pkt_snd, call AMPacket.localGroup());
		call AMPacket.setType(&pkt_snd, 1);
		call Packet.setPayloadLength(&pkt_snd,sizeof(myData_t));
		
		call Timer0.startOneShot(200);
		//return myError;
		return SUCCESS;
	}
	
	event void Timer0.fired(){
		
		error_t myError;
		
		myError = call MulleSend.send(&pkt_snd);
	
		if(myError != SUCCESS){

		}
	}
	
	//event void sendDone(error_t error);
	/*******************************************************************************************************************
	 * 
	 *   Interface AlohaReceive
	 * 
	 ******************************************************************************************************************/
	
	 //event message_t* receiveDone(myData_t* txMsg,error_t error);
	/*******************************************************************************************************************
	 * 
	 *   Interface AlohaState
	 * 
	 ******************************************************************************************************************/
	
	command error_t AlohaState.start(){
		
		error_t myError;
		uint8_t oldState;
	
		if(g_state != STATE_OFF)
			return EBUSY;
			
		atomic  oldState= g_state;
		atomic g_state = STATE_TURNING_ON;
		myError = call MulleState.turnOn();

		if( myError != SUCCESS )
			atomic g_state = oldState; 			
			
		return myError;
	}
	
	command error_t AlohaState.stop(){
		
		error_t myError;
		uint8_t oldState;
		
		if(g_state != STATE_ON)
			return EBUSY;
		
		atomic oldState = g_state;
		atomic g_state = STATE_TURNING_OFF;
		myError = call MulleState.turnOff();

		if( myError != SUCCESS )
			atomic g_state = oldState; 			
			
		return myError;
	}
	
	command error_t AlohaState.setChannel(uint8_t channel){
		
		error_t myError;
		uint8_t oldState;
		
		if(g_state != STATE_ON)
			return EBUSY;
			
		atomic oldState = g_state;
		atomic g_state = STATE_SETTING_CH;
		myError = call MulleState.setChannel(channel);
		
		if( myError != SUCCESS )
			atomic g_state = oldState;
		else
			atomic g_channel = channel;
			
		return myError;
	}
	
	command uint8_t AlohaState.getChannel(){
		
	}
	
	//event void startDone(error_t error);
	//event void stopDone(error_t error);	
	//event void setChannelDone(error_t error);
	
	/*******************************************************************************************************************
	 * 
	 *   Interface RadioSend
	 * 
	 ******************************************************************************************************************/
	/**
	 * Starts the transmission of the given message. This command must not
	 * be called while another send is in progress (so one must wait for the
	 * sendDone event). Returns EBUSY if a reception is in progress or for
	 * some other reason the request cannot be temporarily satisfied (e.g.
	 * the SPI bus access could not be acquired). In this case the send 
	 * command could be retried from a tasklet. Returns SUCCESS if the 
	 * transmission could be started. In this case sendDone will be fired.
	 */
	//tasklet_async command error_t MulleSend.send(message_t* msg)
	
	/**
	 * Signals the completion of the send command, exactly once for each 
	 * successfull send command. If the returned error code is SUCCESS, then 
	 * the message was sent (may not have been acknowledged), otherwise 
	 * the message was not transmitted over the air.
	 */
	
	task void t_RadioSendDone(){
		signal AlohaSend.sendDone(SUCCESS);
	}
	
	tasklet_async event void MulleSend.sendDone(error_t error){
		if(error == SUCCESS){
			atomic g_state = STATE_ON;
			post t_RadioSendDone();
			//call Leds.led1Toggle();
		}else{
			//call Leds.led0Toggle();
		}
	}

	/**
	 * This event is fired when the component is most likely able to accept 
	 * a send request. If the send command has returned with a failure, then
	 * this event will be called at least once in the near future.
	 */
	tasklet_async event void MulleSend.ready(){
		error_t myError;
	
		atomic g_sendState = SENDER_RTX;
	}
	
	/*******************************************************************************************************************
	 * 
	 *   Interface RadioReceive
	 * 
	 ******************************************************************************************************************/
	/**
	 * This event is fired when the header is received/downloaded and the 
	 * higher layers are consulted whether it needs to be downloaded and 
	 * further processed. Return FALSE if the message should be discarded.
	 * In particular, the message buffer layer returns FALSE if there is
	 * no space for a new message, so this message will not get acknowledged.
	 */
	tasklet_async event bool MulleReceive.header(message_t* msg){
		return TRUE;
	}

	/**
	 * Signals the reception of a message, but only for those messages for
	 * which SUCCESS was returned in the header event. The usual owner rules 
	 * apply to the message pointers.
	 */
	 
	task void t_RadioReceiveDone(){
		myData_t* tempData;
		tempData = (myData_t *)(call Packet.getPayload(&pkt_rcv,sizeof(myData_t)));
		g_myData_rcv = *tempData;
		signal AlohaReceive.receiveDone(&g_myData_rcv,SUCCESS);		
	}
	tasklet_async event message_t* MulleReceive.receive(message_t* msg){
		atomic pkt_rcv = *msg;
		post t_RadioReceiveDone();
		return msg;
	}
	/*******************************************************************************************************************
	 * 
	 *   Interface RadioState
	 * 
	 ******************************************************************************************************************/
	
	/**
	 * Moves to radio into sleep state with the lowest power consumption but 
	 * highest wakeup time. The radio cannot send or receive in this state 
	 * and releases all access to shared resources (e.g. SPI bus). 
	 */
	//tasklet_async command error_t turnOff();
	

	/**
	 * The same as the turnOff command, except it is not as deep sleep, and
	 * it is quicker to recover from this state.
	 */
	//tasklet_async command error_t standby();

	/**
	 * Goes into receive state. The radio continuously receive messages 
	 * and able to transmit.
	 */
	//tasklet_async command error_t turnOn();

	/**
	 * Sets the current channel. Returns EBUSY if the stack is unable
	 * to change the channel this time (some other operation is in progress)
	 * SUCCESS otherwise.
	 */
	//tasklet_async command error_t setChannel(uint8_t channel);

	/**
	 * This event is signaled exactly once for each sucessfully posted state 
	 * transition and setChannel command when it is completed.
	 */
	task void t_RadioStateDone(){
		
		switch(g_state){

			case STATE_TURNING_ON:
				atomic g_state = STATE_ON;
				signal AlohaState.startDone(SUCCESS);	
			break;
			case STATE_TURNING_OFF:
				atomic g_state = STATE_OFF;
				signal AlohaState.stopDone(SUCCESS);
			break;
			case STATE_SETTING_CH:
				atomic g_state = STATE_ON;
				signal AlohaState.setChannelDone(SUCCESS);
			break;
			default:
			
		}	
	}
	
	tasklet_async event void MulleState.done(){
		post t_RadioStateDone();
	}

	/**
	 * Returns the currently selected channel.
	 */
	//tasklet_async command uint8_t getChannel();
	
}
